# Always print this out before your assignment
sessionInfo()
R version 4.1.1 (2021-08-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252   
[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] sjmisc_2.8.7                 janitor_2.1.0                randomForestExplainer_0.10.1
 [4] randomForest_4.6-14          titanic_0.1.0                viridis_0.6.2               
 [7] viridisLite_0.4.0            pastecs_1.3.21               kableExtra_1.3.4            
[10] lubridate_1.7.10             rsample_0.1.0                ggthemes_4.2.4              
[13] ggrepel_0.9.1                here_1.0.1                   fs_1.5.0                    
[16] forcats_0.5.1                stringr_1.4.0                dplyr_1.0.7                 
[19] purrr_0.3.4                  readr_2.0.1                  tidyr_1.1.3                 
[22] tibble_3.1.4                 ggplot2_3.3.5                tidyverse_1.3.1             
[25] knitr_1.34                   RSQLite_2.2.8               

loaded via a namespace (and not attached):
 [1] bit64_4.0.5        insight_0.14.4     RColorBrewer_1.1-2 webshot_0.5.2      httr_1.4.2        
 [6] rprojroot_2.0.2    tools_4.1.1        backports_1.2.1    sjlabelled_1.1.8   DT_0.19           
[11] utf8_1.2.2         R6_2.5.1           DBI_1.1.1          colorspace_2.0-2   withr_2.4.2       
[16] GGally_2.1.2       tidyselect_1.1.1   gridExtra_2.3      bit_4.0.4          compiler_4.1.1    
[21] cli_3.0.1          rvest_1.0.1        pacman_0.5.1       xml2_1.3.2         labeling_0.4.2    
[26] pdp_0.7.0          scales_1.1.1       systemfonts_1.0.3  digest_0.6.27      rmarkdown_2.11    
[31] svglite_2.0.0      pkgconfig_2.0.3    htmltools_0.5.2    parallelly_1.28.1  DALEX_2.3.0       
[36] dbplyr_2.1.1       fastmap_1.1.0      htmlwidgets_1.5.4  rlang_0.4.11       readxl_1.3.1      
[41] rstudioapi_0.13    farver_2.1.0       visNetwork_2.1.0   generics_0.1.0     jsonlite_1.7.2    
[46] magrittr_2.0.1     Rcpp_1.0.7         munsell_0.5.0      fansi_0.5.0        lifecycle_1.0.0   
[51] furrr_0.2.3        stringi_1.7.4      yaml_2.2.1         snakecase_0.11.0   plyr_1.8.6        
[56] grid_4.1.1         blob_1.2.2         parallel_4.1.1     listenv_0.8.0      crayon_1.4.1      
[61] lattice_0.20-44    haven_2.4.3        hms_1.1.0          pillar_1.6.2       boot_1.3-28       
[66] codetools_0.2-18   reprex_2.0.1       glue_1.4.2         evaluate_0.14      data.table_1.14.0 
[71] modelr_0.1.8       vctrs_0.3.8        tzdb_0.1.2         cellranger_1.1.0   gtable_0.3.0      
[76] reshape_0.8.8      future_1.22.1      assertthat_0.2.1   cachem_1.0.6       xfun_0.26         
[81] broom_0.7.9        memoise_2.0.0      globals_0.14.0     ellipsis_0.3.2    
getwd()
[1] "C:/BUS_696/final_project/BROCODE_Final_Project"

# load all your libraries in this chunk 
library('tidyverse')
library("fs")
library('here')
library('dplyr')
library('tidyverse')
library('ggplot2')
library('ggrepel')
library('ggthemes')
library('forcats')
library('rsample')
library('lubridate')
library('ggthemes')
library('kableExtra')
library('pastecs')
library('viridis')


# note, do not run install.packages() inside a code chunk. install them in the console outside of a code chunk. 

Final Project Cleaning and Summary Statistics

1a) Loading data


#Reading the data in and doing minor initial cleaning in the function call
#Reproducible data analysis should avoid all automatic string to factor conversions.
#strip.white removes white space 
#na.strings is a substitution so all that have "" will = na
data <- read.csv(here::here("final_project", "donor_data.csv"),
                 stringsAsFactors = FALSE,
                 strip.white = TRUE,
                 na.strings = "")

1b) Fixing the wonky DOB & Data cleanup

1c Creating factor variable for sex


datacleaning <- 
  datacleaning %>% 
  mutate(sex_fct = 
           fct_explicit_na(Sex)
  )


datacleaning <-
datacleaning %>% 
mutate(
  sex_simple = 
    fct_lump_n(Sex, n = 4)
)

#checking to see if its a factor
class(datacleaning$sex_fct)
[1] "factor"
#checking levels
levels(datacleaning$sex_simple)
[1] "F" "M" "U" "X"
#creating a table against Sex column 
table(datacleaning$sex_fct, datacleaning$sex_simple)
           
                 F      M      U      X
  F         120857      0      0      0
  M              0 108322      0      0
  U              0      0   3684      0
  X              0      0      0      7
  (Missing)      0      0      0      0

1d #Mean, Median, and Count of Giving in Age Ranges


age_range_giving <- datacleaning %>%
  group_by(age_range) %>%
  summarise(avg_giving = mean(HH.Lifetime.Giving, na.rm = TRUE),
            med_giving = median(HH.Lifetime.Giving, na.rm = TRUE),
            amount_of_people_in_age_range = n())

Question 2

2a) Plotting average giving by age range


ggplot(age_range_giving, aes(avg_giving, age_range)) +
  geom_bar(stat = "identity")

NA
NA

2b) Count of donors based on age range (another way to look at it)


ggplot(datacleaning, 
       aes(age_range)) + 
       geom_bar() + 
       theme(axis.text.x = element_text(angle=45,
                                        hjust=1)) + 
  labs(title = "Count of Age Ranges", x = "", y = "")
  

2c) Boxplot of the Age Ranges Against the Lifetime Giving Amounts with a log scale applied - the reason we applied log scale is to resolve issues with visualizations that skew towards large values in our dataset.


ggplot(datacleaning, aes(age_range,HH.Lifetime.Giving,fill = age_range)) + 
  geom_boxplot(
  outlier.colour = "red") + 
  scale_y_log10() +
  theme(axis.text.x=element_text(angle=45,hjust=1))
  

2d) Splitting by age and gender



#creating boxplots 
datacleaning %>% 
  filter(Age < 100) %>% #removing the weird outliers that are over 100 
  filter(Sex %in% c("M", "F")) %>%
  ggplot(aes(Sex, Age)) + 
  geom_boxplot() + 
  theme_economist() + 
  ggtitle("Ages of Donors Based on Gender") + 
  xlab(NULL) + ylab(NULL)
  
  
  

2e) Distribution of people in the states that they live.


  datacleaning %>%
  mutate(State = ifelse(State == " ", "NA", State)) %>%
  filter(State != "NA") %>%
  group_by(State) %>%
  summarise(Count = length(State)) %>%
  filter(Count > 800) %>%
  arrange(-Count) %>%
  kable(col.names = c("Donor's State", "Count")) %>%
  kable_styling(bootstrap_options = c("condensed"),
                full_width = F)
  
 
  
  

2f) Looking at all donors first gift amount. 75% made a first gift of <100.


 no_non_donors <- datacleaning %>%
  filter(Lifetime.Giving != 0)
  
nd <- quantile(no_non_donors$HH.First.Gift.Amount, probs = c(.25,.50,.75,.9,.99), na.rm = TRUE)

nd <- as.data.frame(nd)

nd %>%
  kable(col.names = "Quantile") %>%
  kable_styling(bootstrap_options = c("striped", "hover"),
                full_width = F)
  
  

Modeling for you

3a) Linear model

#converting married Y and N to 1 and 0 
datacleaning <- datacleaning %>%
      mutate(Married_simple = ifelse(Married == "N",0,1))
 

mod1lm <- lm( Married ~ Lifetime.Giving,
           data = datacleaning)
Error in lm.fit(x, y, offset = offset, singular.ok = singular.ok, ...) : 
  NA/NaN/Inf in 'y'

3a)

p <- datacleaning %>%
  ggplot(aes(Age)) + geom_histogram(bins=30, fill = "blue") + theme_economist_white() +
  ggtitle("Overall Donor Age Distribution") + 
  xlab(NULL) + ylab(NULL) + scale_x_continuous(breaks = seq(5,100,by = 20)) +
  scale_y_continuous(breaks = seq(20,100,by = 20)) + xlim(c(20,100))
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing
scale.
ggplotly(p)
  
p


ggplot(data = datacleaning, aes(x = Age)) + geom_histogram(fill ="blue")+ xlim(c(20,100))
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

NA
NA
NA
LS0tDQp0aXRsZTogIkJST0NPREUgU3VtbWFyeSBTdGF0aXN0aWNzIg0KYXV0aG9yOiAiQWFyb24sIENhbm5vbiwgSm9zaCwgUnlhbiINCnN1YnRpdGxlOiBGaW5hbCBQcm9qZWN0IFN1bW1hcnkgU3RhdGlzdGljcw0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQoNCiMgUGxlYXNlIGxlYXZlIHRoaXMgY29kZSBjaHVuayBhcyBpcy4gSXQgbWFrZXMgc29tZSBzbGlnaHQgZm9ybWF0dGluZyBjaGFuZ2VzIHRvIGFsdGVyIHRoZSBvdXRwdXQgdG8gYmUgbW9yZSBhZXN0aGV0aWNhbGx5IHBsZWFzaW5nLiANCg0KbGlicmFyeShrbml0cikNCg0KDQojIENoYW5nZSB0aGUgbnVtYmVyIGluIHNldCBzZWVkIHRvIHlvdXIgb3duIGZhdm9yaXRlIG51bWJlcg0Kc2V0LnNlZWQoMTgxOCkNCm9wdGlvbnMod2lkdGg9NzApDQpvcHRpb25zKHNjaXBlbj05OSkNCg0KDQojIHRoaXMgc2V0cyB0ZXh0IG91dHB1dHRlZCBpbiBjb2RlIGNodW5rcyB0byBzbWFsbA0Kb3B0c19jaHVuayRzZXQodGlkeS5vcHRzPWxpc3Qod2lkdGgud3JhcD01MCksdGlkeT1UUlVFLCBzaXplID0gInZzbWFsbCIpICANCm9wdHNfY2h1bmskc2V0KG1lc3NhZ2UgPSBGQUxTRSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICMgImNhY2hpbmciIHN0b3JlcyBvYmplY3RzIGluIGNvZGUgY2h1bmtzIGFuZCBvbmx5IHJld3JpdGVzIGlmIHlvdSBjaGFuZ2UgdGhpbmdzDQogICAgICAgICAgICAgICBjYWNoZSA9IFRSVUUsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgIyBhdXRvbWF0aWNhbGx5IGRvd25sb2FkcyBkZXBlbmRlbmN5IGZpbGVzDQogICAgICAgICAgICAgICBhdXRvZGVwID0gVFJVRSwNCiAgICAgICAgICAgICAgICMgDQogICAgICAgICAgICAgICBjYWNoZS5jb21tZW50cyA9IEZBTFNFLA0KICAgICAgICAgICAgICAgIyANCiAgICAgICAgICAgICAgIGNvbGxhcHNlID0gVFJVRSwNCiAgICAgICAgICAgICAgICMgY2hhbmdlIGZpZy53aWR0aCBhbmQgZmlnLmhlaWdodCB0byBjaGFuZ2UgdGhlIGNvZGUgaGVpZ2h0IGFuZCB3aWR0aCBieSBkZWZhdWx0DQogICAgICAgICAgICAgICBmaWcud2lkdGggPSA1LjUsICANCiAgICAgICAgICAgICAgIGZpZy5oZWlnaHQgPSA0LjUsDQogICAgICAgICAgICAgICBmaWcuYWxpZ249J2NlbnRlcicpDQoNCg0KYGBgDQoNCmBgYHtyIHNldHVwLTJ9DQoNCiMgQWx3YXlzIHByaW50IHRoaXMgb3V0IGJlZm9yZSB5b3VyIGFzc2lnbm1lbnQNCnNlc3Npb25JbmZvKCkNCmdldHdkKCkNCg0KYGBgDQoNCg0KPCEtLSAjIyMgc3RhcnQgYW5zd2VyaW5nIHlvdXIgcHJvYmxlbSBzZXQgaGVyZSAtLT4NCjwhLS0gWW91IG1heSBleHBvcnQgeW91ciBob21ld29yayBpbiBlaXRoZXIgaHRtbCBvciBwZGYsIHdpdGggdGhlIGZvcm1lciB1c3VhbGx5IGJlaW5nIGVhc2llci4gDQogICAgIFRvIGV4cG9ydCBvciBjb21waWxlIHlvdXIgUm1kIGZpbGU6IGNsaWNrIGFib3ZlIG9uICdLbml0JyB0aGVuICdLbml0IHRvIEhUTUwnIC0tPg0KPCEtLSBCZSBzdXJlIHRvIHN1Ym1pdCBib3RoIHlvdXIgLlJtZCBmaWxlIGFuZCB0aGUgY29tcGlsZWQgLmh0bWwgb3IgLnBkZiBmaWxlIGZvciBmdWxsIGNyZWRpdCAtLT4NCg0KDQpgYGB7ciBzZXR1cC0zfQ0KDQojIGxvYWQgYWxsIHlvdXIgbGlicmFyaWVzIGluIHRoaXMgY2h1bmsgDQpsaWJyYXJ5KCd0aWR5dmVyc2UnKQ0KbGlicmFyeSgiZnMiKQ0KbGlicmFyeSgnaGVyZScpDQpsaWJyYXJ5KCdkcGx5cicpDQpsaWJyYXJ5KCd0aWR5dmVyc2UnKQ0KbGlicmFyeSgnZ2dwbG90MicpDQpsaWJyYXJ5KCdnZ3JlcGVsJykNCmxpYnJhcnkoJ2dndGhlbWVzJykNCmxpYnJhcnkoJ2ZvcmNhdHMnKQ0KbGlicmFyeSgncnNhbXBsZScpDQpsaWJyYXJ5KCdsdWJyaWRhdGUnKQ0KbGlicmFyeSgnZ2d0aGVtZXMnKQ0KbGlicmFyeSgna2FibGVFeHRyYScpDQpsaWJyYXJ5KCdwYXN0ZWNzJykNCmxpYnJhcnkoJ3ZpcmlkaXMnKQ0KbGlicmFyeSgncGxvdGx5JykNCg0KDQojIG5vdGUsIGRvIG5vdCBydW4gaW5zdGFsbC5wYWNrYWdlcygpIGluc2lkZSBhIGNvZGUgY2h1bmsuIGluc3RhbGwgdGhlbSBpbiB0aGUgY29uc29sZSBvdXRzaWRlIG9mIGEgY29kZSBjaHVuay4gDQoNCmBgYA0KDQoNCg0KIyMgRmluYWwgUHJvamVjdCBDbGVhbmluZyBhbmQgU3VtbWFyeSBTdGF0aXN0aWNzIA0KDQoxYSkgTG9hZGluZyBkYXRhDQoNCmBgYHtyfQ0KDQojUmVhZGluZyB0aGUgZGF0YSBpbiBhbmQgZG9pbmcgbWlub3IgaW5pdGlhbCBjbGVhbmluZyBpbiB0aGUgZnVuY3Rpb24gY2FsbA0KI1JlcHJvZHVjaWJsZSBkYXRhIGFuYWx5c2lzIHNob3VsZCBhdm9pZCBhbGwgYXV0b21hdGljIHN0cmluZyB0byBmYWN0b3IgY29udmVyc2lvbnMuDQojc3RyaXAud2hpdGUgcmVtb3ZlcyB3aGl0ZSBzcGFjZSANCiNuYS5zdHJpbmdzIGlzIGEgc3Vic3RpdHV0aW9uIHNvIGFsbCB0aGF0IGhhdmUgIiIgd2lsbCA9IG5hDQpkYXRhIDwtIHJlYWQuY3N2KGhlcmU6OmhlcmUoImZpbmFsX3Byb2plY3QiLCAiZG9ub3JfZGF0YS5jc3YiKSwNCiAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICBzdHJpcC53aGl0ZSA9IFRSVUUsDQogICAgICAgICAgICAgICAgIG5hLnN0cmluZ3MgPSAiIikNCg0KYGBgDQoNCg0KMWIpIEZpeGluZyB0aGUgd29ua3kgRE9CICYgRGF0YSBjbGVhbnVwDQoNCmBgYHtyfQ0KDQojKEJpcnRoZGF0ZSBhbmQgQWdlLCBJRCBhcyBhIG51bWJlcilhZGRpbmcgRE9CIChBZ2UvU3BvdXNlIEFnZSkgaW4geWVhcnMgY29sdW1ucyBhbmQgYWRkaW5nIHR3byBmaWVsZHMgZm9yIGFzc2lnbm1lbnQgYW5kIG51bWJlciBvZiBjaGlsZHJlbg0KZGF0YWNsZWFuaW5nIDwtIGRhdGEgJT4lDQogIG11dGF0ZShCaXJ0aGRhdGUgPSBpZmVsc2UoQmlydGhkYXRlID09ICIwMDAxLTAxLTAxIiwgTkEsIEJpcnRoZGF0ZSkpICU+JQ0KICBtdXRhdGUoQmlydGhkYXRlID0gbWR5KEJpcnRoZGF0ZSkpICU+JQ0KICBtdXRhdGUoQWdlID0gYXMubnVtZXJpYyhmbG9vcihpbnRlcnZhbChzdGFydD0gQmlydGhkYXRlLCBlbmQ9U3lzLkRhdGUoKSkvZHVyYXRpb24obj0xLCB1bml0PSJ5ZWFycyIpKSkpICU+JQ0KICBtdXRhdGUoU3BvdXNlLkJpcnRoZGF0ZSA9IGlmZWxzZShTcG91c2UuQmlydGhkYXRlID09ICIwMDAxLTAxLTAxIiwgTkEsIFNwb3VzZS5CaXJ0aGRhdGUpKSAlPiUNCiAgbXV0YXRlKFNwb3VzZS5CaXJ0aGRhdGUgPSBtZHkoU3BvdXNlLkJpcnRoZGF0ZSkpICU+JQ0KICBtdXRhdGUoU3BvdXNlLkFnZSA9IGFzLm51bWVyaWMoZmxvb3IoaW50ZXJ2YWwoc3RhcnQ9IFNwb3VzZS5CaXJ0aGRhdGUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ9U3lzLkRhdGUoKSkvZHVyYXRpb24obj0xLCB1bml0PSJ5ZWFycyIpKSkpICU+JQ0KICBtdXRhdGUoSUQgPSBhcy5udW1lcmljKElEKSkgJT4lIA0KICBtdXRhdGUoQXNzaWdubWVudF9mbGFnID0gaWZlbHNlKGlzLm5hKEFzc2lnbm1lbnQuTnVtYmVyKSwgMCwxKSkgJT4lIA0KICBtdXRhdGUoIE5vX29mX0NoaWxkcmVuID0gaWZlbHNlKGlzLm5hKENoaWxkLjEuSUQpLDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGlzLm5hKENoaWxkLjIuSUQpLDEsMikpKQ0KDQojc3BsaXR0aW5nIHVwIHRoZSBhZ2UgaW50byByYW5nZXMgYW5kIGNyZWF0aW5nIGNhdGVnb3J5IGZvciBlYXN5IHZpc3VhbGl6YXRpb24gDQpkYXRhY2xlYW5pbmcgPC0gZGF0YWNsZWFuaW5nICU+JQ0KICBtdXRhdGUoYWdlX3JhbmdlID0gDQogICAgaWZlbHNlKEFnZSAlaW4lIDEwOjE5LCAiMTAgPCAyMCB5ZWFyIG9sZHMiLA0KICAgIGlmZWxzZShBZ2UgJWluJSAyMDoyOSwgIjIwIDwgMzAgeWVhciBvbGRzIiwgDQogICAgaWZlbHNlKEFnZSAlaW4lIDMwOjM5LCAiMzAgPCA0MCB5ZWFyIG9sZHMiLA0KICAgIGlmZWxzZShBZ2UgJWluJSA0MDo0OSwgIjQwIDwgNTAgeWVhciBvbGRzIiwNCiAgICBpZmVsc2UoQWdlICVpbiUgNTA6NTksICI1MCA8IDYwIHllYXIgb2xkcyIsDQogICAgaWZlbHNlKEFnZSAlaW4lIDYwOjY5LCAiNjAgPCA3MCB5ZWFyIG9sZHMiLA0KICAgIGlmZWxzZShBZ2UgJWluJSA3MDo3OSwgIjcwIDwgODAgeWVhciBvbGRzIiwNCiAgICBpZmVsc2UoQWdlICVpbiUgODA6ODksICI4MCA8IDkwIHllYXIgb2xkcyIsDQogICAgaWZlbHNlKEFnZSAlaW4lIDkwOjk5LCAiOTAgPCAxMDAgeWVhciBvbGRzIiwNCiAgICBpZmVsc2UoQWdlICVpbiUgMTAwOjEwOSwgIjEwMCA8IDExMCB5ZWFyIG9sZHMiLA0KICAgIGlmZWxzZShBZ2UgJWluJSAxMTA6MTIwLCAiMTEwIC0gMTIwICB5ZWFyIG9sZHMiLA0KICAgIE5BKSkpKSkpKSkpKSkpDQoNCiNzZWVpbmcgd2hhdCB3ZSBoYXZlDQp0YWJsZShkYXRhY2xlYW5pbmckYWdlX3JhbmdlKQ0KIzUwLTYwIGlzIHRoZSBtb3N0IGNvbW1vbiBhZ2UgcmFuZ2UgDQoNCiNSZW1vdmluZyBDb2x1bW5zIHRoYXQgcHJvdmlkZSBubyBiZW5lZml0IA0KDQpkYXRhX2NsZWFuZWRfY29sdW1ucyA8LSBzdWJzZXQoZGF0YWNsZWFuaW5nLHNlbGVjdCA9IC1jKEFzc2lnbm1lbnQuTnVtYmVyDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxBc3NpZ25tZW50Lmhhcy5IaXN0b3JpY2FsLk1uZ3INCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuRGF0ZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsQXNzaWdubWVudC5NYW5hZ2VyDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxBc3NpZ25tZW50LlJvbGUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuVGl0bGUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuU3RhdHVzDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxTdHJhdGVneQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsUHJvZ3Jlc3MuTGV2ZWwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuR3JvdXANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEFzc2lnbm1lbnQuQ2F0ZWdvcnkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLEZ1bmRpbmcuTWV0aG9kDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxFeHBlY3RlZC5Cb29rLkRhdGUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFF1YWxpZmljYXRpb24uQW1vdW50DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxFeHBlY3RlZC5Cb29rLkFtb3VudA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsRXhwZWN0ZWQuQm9vay5EYXRlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxIYXJkLkdpZnQuVG90YWwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLFNvZnQuQ3JlZGl0LlRvdGFsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxUb3RhbC5Bc3NpZ25tZW50LkdpZnRzDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxOby5vZi5QbGVkZ2VzDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxQcm9wb3NhbC4uDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxQcm9wb3NhbC5Ob3Rlcw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsSEguTGlmZS5IYXJkLkNyZWRpdA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsSEguTGlmZS5Tb2Z0LkNyZWRpdA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsSEguTGlmZS5TcG91c2UuQ3JlZGl0DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICxMYXN0LkNvbnRhY3QuQnkuTWFuYWdlcg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsWC4ub2YuQ29udGFjdHMuQnkuTWFuYWdlcikpDQogIA0KI2NoZWNraW5nIGZvciBkdXBsaWNhdGVzIE4gPjEgaW5kaWNhdGVzIGEgcmVjb3JkcyB2YWx1ZXMgYXJlIGluIHRoZSBmaWxlIHR3aWNlIA0KZGF0YV9jbGVhbmVkX2NvbHVtbnMgJT4lIGdyb3VwX2J5KElEKSAlPiUgY291bnQoKSAlPiUgYXJyYW5nZShkZXNjKG4pKQ0KDQojcmVtb3ZpbmcgZHVwbGljYXRlZCByZWNvcmRzDQoNCmRhdGFfY2xlYW5lZCA8LSB1bmlxdWUoZGF0YV9jbGVhbmVkX2NvbHVtbnMpDQoNCiNuID0gMSBubyBJRCB3aXRoIG11bHRpcGxlIHJlY29yZHMgY2xlYW5lZCBvZiBkdXBlcw0KZGF0YV9jbGVhbmVkICU+JSBncm91cF9ieShJRCkgJT4lIGNvdW50KCkgJT4lIGFycmFuZ2UoZGVzYyhuKSkNCg0KYGBgDQoNCjFjIENyZWF0aW5nIGZhY3RvciB2YXJpYWJsZSBmb3Igc2V4IA0KDQpgYGB7cn0NCg0KZGF0YV9jbGVhbmVkIDwtIA0KICBkYXRhX2NsZWFuZWQgJT4lIA0KICBtdXRhdGUoc2V4X2ZjdCA9IA0KICAgICAgICAgICBmY3RfZXhwbGljaXRfbmEoU2V4KQ0KICApDQoNCg0KZGF0YV9jbGVhbmVkIDwtDQpkYXRhX2NsZWFuZWQgJT4lIA0KbXV0YXRlKA0KICBzZXhfc2ltcGxlID0gDQogICAgZmN0X2x1bXBfbihTZXgsIG4gPSA0KQ0KKQ0KDQojY2hlY2tpbmcgdG8gc2VlIGlmIGl0cyBhIGZhY3Rvcg0KY2xhc3MoZGF0YV9jbGVhbmVkJHNleF9mY3QpDQoNCiNjaGVja2luZyBsZXZlbHMNCmxldmVscyhkYXRhX2NsZWFuZWQkc2V4X3NpbXBsZSkNCg0KI2NyZWF0aW5nIGEgdGFibGUgYWdhaW5zdCBTZXggY29sdW1uIA0KdGFibGUoZGF0YV9jbGVhbmVkJHNleF9mY3QsIGRhdGFfY2xlYW5lZCRzZXhfc2ltcGxlKQ0KDQoNCmBgYA0KDQoNCg0KDQpgYGB7cn0NCg0KDQoNCmBgYA0KDQoxZCAjTWVhbiwgTWVkaWFuLCBhbmQgQ291bnQgb2YgR2l2aW5nIGluIEFnZSBSYW5nZXMgDQoNCmBgYHtyfQ0KDQphZ2VfcmFuZ2VfZ2l2aW5nIDwtIGRhdGFjbGVhbmluZyAlPiUNCiAgZ3JvdXBfYnkoYWdlX3JhbmdlKSAlPiUNCiAgc3VtbWFyaXNlKGF2Z19naXZpbmcgPSBtZWFuKEhILkxpZmV0aW1lLkdpdmluZywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIG1lZF9naXZpbmcgPSBtZWRpYW4oSEguTGlmZXRpbWUuR2l2aW5nLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgYW1vdW50X29mX3Blb3BsZV9pbl9hZ2VfcmFuZ2UgPSBuKCkpDQoNCg0KDQpgYGANCg0KDQoNCg0KDQojIyBRdWVzdGlvbiAyDQoNCjJhKSBQbG90dGluZyBhdmVyYWdlIGdpdmluZyBieSBhZ2UgcmFuZ2UgDQoNCg0KYGBge3J9DQoNCmdncGxvdChhZ2VfcmFuZ2VfZ2l2aW5nLCBhZXMoYXZnX2dpdmluZywgYWdlX3JhbmdlKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikNCg0KDQpgYGANCg0KDQoyYikgQ291bnQgb2YgZG9ub3JzIGJhc2VkIG9uIGFnZSByYW5nZSAoYW5vdGhlciB3YXkgdG8gbG9vayBhdCBpdCkNCg0KDQpgYGB7cn0NCg0KZ2dwbG90KGRhdGFjbGVhbmluZywgDQogICAgICAgYWVzKGFnZV9yYW5nZSkpICsgDQogICAgICAgZ2VvbV9iYXIoKSArIA0KICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0PTEpKSArIA0KICBsYWJzKHRpdGxlID0gIkNvdW50IG9mIEFnZSBSYW5nZXMiLCB4ID0gIiIsIHkgPSAiIikNCiAgDQoNCmBgYA0KDQoyYykgQm94cGxvdCBvZiB0aGUgQWdlIFJhbmdlcyBBZ2FpbnN0IHRoZSBMaWZldGltZSBHaXZpbmcgQW1vdW50cyB3aXRoIGEgbG9nIHNjYWxlIGFwcGxpZWQgLSB0aGUgcmVhc29uIHdlIGFwcGxpZWQgbG9nIHNjYWxlIGlzIHRvIHJlc29sdmUgaXNzdWVzIHdpdGggdmlzdWFsaXphdGlvbnMgdGhhdCBza2V3IHRvd2FyZHMgbGFyZ2UgdmFsdWVzIGluIG91ciBkYXRhc2V0LiANCg0KDQpgYGB7cn0NCg0KZ2dwbG90KGRhdGFjbGVhbmluZywgYWVzKGFnZV9yYW5nZSxISC5MaWZldGltZS5HaXZpbmcsZmlsbCA9IGFnZV9yYW5nZSkpICsgDQogIGdlb21fYm94cGxvdCgNCiAgb3V0bGllci5jb2xvdXIgPSAicmVkIikgKyANCiAgc2NhbGVfeV9sb2cxMCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LGhqdXN0PTEpKQ0KICANCg0KYGBgDQoNCjJkKSBTcGxpdHRpbmcgYnkgYWdlIGFuZCBnZW5kZXIgDQoNCg0KYGBge3J9DQoNCg0KI2NyZWF0aW5nIGJveHBsb3RzIA0KZGF0YWNsZWFuaW5nICU+JSANCiAgZmlsdGVyKEFnZSA8IDEwMCkgJT4lICNyZW1vdmluZyB0aGUgd2VpcmQgb3V0bGllcnMgdGhhdCBhcmUgb3ZlciAxMDAgDQogIGZpbHRlcihTZXggJWluJSBjKCJNIiwgIkYiKSkgJT4lDQogIGdncGxvdChhZXMoU2V4LCBBZ2UpKSArIA0KICBnZW9tX2JveHBsb3QoKSArIA0KICB0aGVtZV9lY29ub21pc3QoKSArIA0KICBnZ3RpdGxlKCJBZ2VzIG9mIERvbm9ycyBCYXNlZCBvbiBHZW5kZXIiKSArIA0KICB4bGFiKE5VTEwpICsgeWxhYihOVUxMKQ0KICANCiAgDQogIA0KDQoNCmBgYA0KDQoyZSkgRGlzdHJpYnV0aW9uIG9mIHBlb3BsZSBpbiB0aGUgc3RhdGVzIHRoYXQgdGhleSBsaXZlLg0KDQpgYGB7cn0NCg0KICBkYXRhY2xlYW5pbmcgJT4lDQogIG11dGF0ZShTdGF0ZSA9IGlmZWxzZShTdGF0ZSA9PSAiICIsICJOQSIsIFN0YXRlKSkgJT4lDQogIGZpbHRlcihTdGF0ZSAhPSAiTkEiKSAlPiUNCiAgZ3JvdXBfYnkoU3RhdGUpICU+JQ0KICBzdW1tYXJpc2UoQ291bnQgPSBsZW5ndGgoU3RhdGUpKSAlPiUNCiAgZmlsdGVyKENvdW50ID4gODAwKSAlPiUNCiAgYXJyYW5nZSgtQ291bnQpICU+JQ0KICBrYWJsZShjb2wubmFtZXMgPSBjKCJEb25vcidzIFN0YXRlIiwgIkNvdW50IikpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygiY29uZGVuc2VkIiksDQogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEYpDQogIA0KIA0KICANCiAgDQoNCg0KYGBgDQoNCjJmKSBMb29raW5nIGF0IGFsbCBkb25vcnMgZmlyc3QgZ2lmdCBhbW91bnQuIDc1JSBtYWRlIGEgZmlyc3QgZ2lmdCBvZiA8MTAwLiANCg0KYGBge3J9DQoNCiBub19ub25fZG9ub3JzIDwtIGRhdGFjbGVhbmluZyAlPiUNCiAgZmlsdGVyKExpZmV0aW1lLkdpdmluZyAhPSAwKQ0KICANCm5kIDwtIHF1YW50aWxlKG5vX25vbl9kb25vcnMkSEguRmlyc3QuR2lmdC5BbW91bnQsIHByb2JzID0gYyguMjUsLjUwLC43NSwuOSwuOTkpLCBuYS5ybSA9IFRSVUUpDQoNCm5kIDwtIGFzLmRhdGEuZnJhbWUobmQpDQoNCm5kICU+JQ0KICBrYWJsZShjb2wubmFtZXMgPSAiUXVhbnRpbGUiKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwNCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRikNCiAgDQogIA0KDQoNCmBgYA0KDQoNCg0KIyMgTW9kZWxpbmcgZm9yIHlvdSANCg0KDQozYSkgTGluZWFyIG1vZGVsIA0KDQpgYGB7cn0NCiNjb252ZXJ0aW5nIG1hcnJpZWQgWSBhbmQgTiB0byAxIGFuZCAwIA0KZGF0YWNsZWFuaW5nIDwtIGRhdGFjbGVhbmluZyAlPiUNCiAgICAgIG11dGF0ZShNYXJyaWVkX3NpbXBsZSA9IGlmZWxzZShNYXJyaWVkID09ICJOIiwwLDEpKQ0KIA0KDQptb2QxbG0gPC0gbG0oIE1hcnJpZWRfc2ltcGxlIH4gTGlmZXRpbWUuR2l2aW5nLA0KICAgICAgICAgICBkYXRhID0gZGF0YWNsZWFuaW5nKQ0KDQpzdW1tYXJ5KG1vZDFsbSkNCiAgDQoNCg0KYGBgDQozYSkgDQoNCmBgYHtyfQ0KcCA8LSBkYXRhY2xlYW5pbmcgJT4lDQogIGdncGxvdChhZXMoQWdlKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW5zPTMwLCBmaWxsID0gImJsdWUiKSArIHRoZW1lX2Vjb25vbWlzdF93aGl0ZSgpICsNCiAgZ2d0aXRsZSgiT3ZlcmFsbCBEb25vciBBZ2UgRGlzdHJpYnV0aW9uIikgKyANCiAgeGxhYihOVUxMKSArIHlsYWIoTlVMTCkgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDUsMTAwLGJ5ID0gMjApKSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMjAsMTAwLGJ5ID0gMjApKSArIHhsaW0oYygyMCwxMDApKQ0KDQpnZ3Bsb3RseShwKQ0KICANCnANCg0KZ2dwbG90KGRhdGEgPSBkYXRhY2xlYW5pbmcsIGFlcyh4ID0gQWdlKSkgKyBnZW9tX2hpc3RvZ3JhbShmaWxsID0iYmx1ZSIpKyB4bGltKGMoMjAsMTAwKSkNCg0KICANCg0KDQpgYGANCg==